#include <iostream>
#include <signal.h>     // sigemptyset(), sigaddset(), sigprocmask(), sigpending(), sigismember()
#include <string.h>     // strerror()
#include <unistd.h>     // sleep(), getpid()
#include <sys/types.h>  // getpid()

using namespace std;

// ----- this test using -----
// the signal of No.2 needs to be conveyed to the progress separately before and after the command of sigprocmask been called

void PringPending(const sigset_t& pending)
{
    cout << "signal pending:";
    for(int i = 31; i >= 0; i--)
    {
        if(sigismember(&pending, i))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}

void handler(int signo)
{
    cout << "Catch signal of No.2, no exit" << endl;
}

void test()
{
    // custom catch the signal of No.2
    signal(2, handler);

    // 1. block signal of No.2
    sigset_t block, old_block;
    sigemptyset(&block);
    sigemptyset(&old_block);
    sigaddset(&block, 2);   // write to stack variable
    sleep(10);

    int n = sigprocmask(SIG_SETMASK, &block, &old_block);   // set into PCB block bitmap of the current process
    if(n == -1)
    {
        cout << "error: test()::sigprocmask() -- error str: " << strerror(errno) << endl;
    }
    else
    {
        cout << "block 2 signal success !" << endl;
    }
    cout << "process pid: " << getpid() << endl;

    for(int cnt = 0; cnt < 30; ++cnt)
    {
        // 2. get the pending bitmap of the process
        sigset_t pending;
        sigemptyset(&pending);
        sigpending(&pending);

        // 3.demonstrate the pending bitmap
        PringPending(pending);

        // 4. unblock signal No.2
        if(cnt == 20)
        {
            sigprocmask(SIG_UNBLOCK, &block, &old_block);
            cout << "unblock signal No.2 is success" << endl;
        }

        sleep(1);
    }
}


int main()
{
    test();
    return 0;
}